package com.fubowen.reader.db.dao

import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import androidx.room.Upsert
import com.fubowen.reader.db.bean.BookBean
import com.fubowen.reader.db.bean.BookChapterBean
import com.fubowen.reader.db.model.BookCatalog
import kotlinx.coroutines.flow.Flow

@Dao
interface BookDao {
    @Query("select * from BookBean")
    fun all(): List<BookBean>

    @Query("select a.* from BookBean a")
    fun allFlow(): Flow<List<BookBean>>

    @Query("select * from BookBean where Id = :id")
    fun get(id: Int): BookBean

    @Insert
    fun set(bean: BookBean): Long

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun setOrIgnore(bean: BookBean): Long

    @Update
    fun put(bean: BookBean)

    @Upsert
    fun setOrPut(bean: BookBean)

    @Delete
    fun del(bean: BookBean)

    @Query("DELETE FROM BookBean")
    fun clear()

    //region BookBean 类的扩展方法
    @Query("select * from BookBean where url = :absolutePath")
    fun getByAbsolutePath(absolutePath: String): BookBean?

    @Query("SELECT * FROM BookBean WHERE isReading = 1")
    fun getReadingBookFlow(): Flow<BookBean?>

    @Query("SELECT * FROM BookBean WHERE isReading = 1")
    fun getReadingBook(): BookBean?

    @Query("UPDATE BookBean SET isReading = :isReading  WHERE id = :bookId")
    fun setReadingBook(bookId: Int, isReading: Boolean)

    @Transaction
    fun changeReadingBook(bookId: Int) {
        val book = getReadingBook()
        if (book != null) {
            if (book.id != bookId) {
                setReadingBook(book.id, isReading = false)
            }
        } else {
            setReadingBook(bookId, isReading = true)
        }
    }

    @Query("UPDATE BookBean SET readingChapter = :readingChapter,readingChapterName=:name  WHERE id = :bookId")
    fun setReadingChapterOfBook(bookId: Int, readingChapter: Int, name: String)

    //endregion

    //region BookChapterBean 类的扩展方法
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun setOrIgnoreChapter(bean: BookChapterBean)

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun setOrIgnoreChapter(bean: List<BookChapterBean>)

    @Query("select * from BookChapterBean where bookId = :bookId order by `order`")
    fun getChapterList(bookId: Int): List<BookChapterBean>

    @Query("select * from BookChapterBean where bookId = :bookId and isDownload=:isDownload order by `order`")
    fun getChapterList(bookId: Int, isDownload: Boolean): List<BookChapterBean>

    @Query("select * from BookChapterBean where bookId = :bookId and id = :chapterId")
    fun getChapterById(bookId: Int, chapterId: Int): BookChapterBean?

    @Query("select * from BookChapterBean where bookId = :bookId order by `order`")
    fun getChapterFlow(bookId: Int): Flow<List<BookChapterBean>>

    @Query("select * from BookChapterBean where bookId = :bookId order by `order`")
    fun getCatalogFlow(bookId: Int): Flow<List<BookCatalog>>

    @Query("select * from BookChapterBean where bookId=:bookId and isReading = 1")
    fun getReadingChapter(bookId: Int): BookChapterBean?

    @Query("UPDATE BookChapterBean SET isReading = :isReading  WHERE bookId=:bookId and id = :chapterId")
    fun setReadingChapter(bookId: Int, chapterId: Int, isReading: Boolean)

    @Query("UPDATE BookChapterBean SET isReading = :isReading,position=:position  WHERE bookId=:bookId and id = :chapterId")
    fun setReadingChapter(bookId: Int, chapterId: Int, isReading: Boolean, position: Int)

    @Transaction
    fun changeReadingChapter(bookId: Int, chapterId: Int, position: Int) {
        val oldChapter = getReadingChapter(bookId)
        val newChapter = getChapterById(bookId, chapterId)
        if (oldChapter != null) {
            if (oldChapter.bookId == bookId && oldChapter.id != chapterId) {
                val next = oldChapter.order + 1
                if (chapterId == next) {
                    setReadingChapter(oldChapter.bookId, oldChapter.id, false, -1)
                } else {
                    setReadingChapter(oldChapter.bookId, oldChapter.id, false)
                }
            }
        }

        if (newChapter != null) {
            if (position > newChapter.position) {
                setReadingChapter(bookId, chapterId, true, position)
            } else {
                setReadingChapter(bookId, chapterId, true)
            }
            if (oldChapter?.bookId != bookId || oldChapter.id != chapterId) {
                setReadingChapterOfBook(newChapter.bookId, newChapter.order, newChapter.name)
            }
        }
    }

    @Query("UPDATE BookChapterBean SET content = :content,charCount=:words,isDownload = 1  WHERE id = :chapterId")
    fun setChapterContent(chapterId: Int, content: String, words: Int)

    @Query("select * from BookChapterBean where bookId=:bookId limit :takeCount offset :skipCount")
    fun getPageChapter(bookId: Int, takeCount: Int, skipCount: Int): List<BookChapterBean>

    @Query("select * from BookChapterBean where bookId=:bookId")
    fun bookChapter(bookId: Int): PagingSource<Int, BookChapterBean>

    @Query("UPDATE BookChapterBean SET content=:content,isDownload=:isDownload,charCount=:charCount  WHERE id=:chapterId")
    fun setChapterContent(chapterId: Int, content: String,charCount:Int, isDownload: Boolean)

    //endregion
}